///////////////////////////////////////////////////////////////////////////////

#ifndef _MATHFUNCTIONS_H_
#include "mathfunctions.h"
#endif

#ifndef _CIRCLE_H_
#include "circle.h"
#endif

#ifndef _POLYGON_H_
#include "polygon.h"
#endif

////////////////////////////////////////////////////////////////////////////////

#include <math.h>
#include <cstdlib>

////////////////////////////////////////////////////////////////////////////////

namespace PE
{
////////////////////////////////////////////////////////////////////////////////
// Mathematical functions
////////////////////////////////////////////////////////////////////////////////


double VectorLength( const Vector& _v )
{
    return pow((_v.vx * _v.vx + _v.vy * _v.vy), 0.5);
}


////////////////////////////////////////////////////////////////////////////////


double Cos2Vectors( const Vector& _v1, const Vector& _v2)
{
    return (_v1.vx * _v2.vx + _v1.vy * _v2.vy) /
           (VectorLength(_v1) * VectorLength(_v2));
}


////////////////////////////////////////////////////////////////////////////////


double Distance( const Point& _p1, const Point& _p2 )
{
    return pow((_p1.x - _p2.x) * (_p1.x - _p2.x) +
        (_p1.y - _p2.y) * (_p1.y - _p2.y), 0.5);
}


////////////////////////////////////////////////////////////////////////////////


Direction GetDirection( const Vector& _v )
{
    double len = VectorLength(_v);

    Direction dir = {0, 0};

    if (abs(len) > _E)
    {
        dir.dx = _v.vx / len;
        dir.dy = _v.vy / len;
    }
    
    return dir;
}


////////////////////////////////////////////////////////////////////////////////


bool IntersectCircleWithLine( const Point& _circlePt, const Circle& _circle, const Line& _line, PE::Point& _tangency )
{
    // Get line length and direction
    Vector lineVec = {_line.pE.x - _line.pS.x, _line.pE.y - _line.pS.y};
    double lineLength = VectorLength(lineVec);

    Direction lineDir = GetDirection(lineVec);

    // Calculate distance between circle center and line end
    Vector dist = {_line.pS.x - _circlePt.x, _line.pS.y - _circlePt.y};
    
    // Resolve square equation
    double b = 2 * (dist.vx * lineDir.dx + dist.vy * lineDir.dy);
    double c = dist.vx * dist.vx + dist.vy * dist.vy - _circle.m_Radius * _circle.m_Radius;
    double c4 = (c + c) * 2;
    double D = b * b - c4;

    // No solutions
    if (D < 0)
        return false;

    D = sqrt(D);
    double l1 = ( - b + D) * 0.5;
    double l2 = ( - b - D) * 0.5;

    bool intersects1 = ((l1 >= 0.0) && (l1 <= lineLength));
    bool intersects2 = ((l2 >= 0.0) && (l2 <= lineLength));
    if (intersects1 || intersects2)
    {
        if (intersects1 && intersects2) 
            l1 = (l1 + l2) * 0.5;
        else if (intersects2)
            l1 = l2;

        _tangency.x = _line.pS.x + lineDir.dx * l1;
        _tangency.y = _line.pS.y + lineDir.dy * l1;
        
        return true;
    }

    return false;
}


////////////////////////////////////////////////////////////////////////////////

};

////////////////////////////////////////////////////////////////////////////////
